﻿using System;

namespace OmniKits.Windows.Interop
{
    partial class COM
    {
        public const int FLAG_SEVERITY = unchecked((int)0x80000000);
        public const int FLAG_RESERVED = 0x40000000;
        public const int FLAG_CUSTOMER = 0x20000000;
        public const int FLAG_NTSTATUS = 0x10000000;
        public const int FLAG_X = 0x8000000;

        #region Facilities

        public const int FACILITY_NULL = 0;
        public const int FACILITY_RPC = 1;
        public const int FACILITY_DISPATCH = 2;
        public const int FACILITY_STORAGE = 3;
        public const int FACILITY_ITF = 4;
        public const int FACILITY_WIN32 = 7;
        public const int FACILITY_WINDOWS = 8;
        public const int FACILITY_SECURITY = 9;
        public const int FACILITY_SSPI = 9;
        public const int FACILITY_CONTROL = 10;
        public const int FACILITY_CERT = 11;
        public const int FACILITY_INTERNET = 12;
        public const int FACILITY_MEDIASERVER = 13;
        public const int FACILITY_MSMQ = 14;
        public const int FACILITY_SETUPAPI = 15;
        public const int FACILITY_SCARD = 16;
        public const int FACILITY_COMPLUS = 17;
        public const int FACILITY_AAF = 18;
        public const int FACILITY_URT = 19;
        public const int FACILITY_ACS = 20;
        public const int FACILITY_DPLAY = 21;
        public const int FACILITY_UMI = 22;
        public const int FACILITY_SXS = 23;
        public const int FACILITY_WINDOWS_CE = 24;
        public const int FACILITY_HTTP = 25;
        public const int FACILITY_USERMODE_COMMONLOG = 26;

        public const int FACILITY_USERMODE_FILTER_MANAGER = 31;
        public const int FACILITY_BACKGROUNDCOPY = 32;
        public const int FACILITY_CONFIGURATION = 33;
        public const int FACILITY_STATE_MANAGEMENT = 34;
        public const int FACILITY_METADIRECTORY = 35;
        public const int FACILITY_WINDOWSUPDATE = 36;
        public const int FACILITY_DIRECTORYSERVICE = 37;
        public const int FACILITY_GRAPHICS = 38;
        public const int FACILITY_SHELL = 39;

        public const int FACILITY_TPM_SERVICES = 40;
        public const int FACILITY_TPM_SOFTWARE = 41;

        public const int FACILITY_PLA = 48;
        public const int FACILITY_FVE = 49;

        public const int FACILITY_FWP = 50;
        public const int FACILITY_WINRM = 51;
        public const int FACILITY_NDIS = 52;
        public const int FACILITY_USERMODE_HYPERVISOR = 53;
        public const int FACILITY_CMI = 54;
        public const int FACILITY_USERMODE_VIRTUALIZATION = 55;
        public const int FACILITY_USERMODE_VOLMGR = 56;
        public const int FACILITY_BCD = 57;
        public const int FACILITY_USERMODE_VHD = 58;

        public const int FACILITY_SDIAG = 60;
        public const int FACILITY_WEBSERVICES = 61;

        public const int FACILITY_WINDOWS_DEFENDER = 80;
        public const int FACILITY_OPC = 81;

        #endregion

        #region Facilities as a part of HResult

        public const int PART_FACILITY_NULL = FACILITY_NULL << 16;
        public const int PART_FACILITY_RPC = FACILITY_RPC << 16;
        public const int PART_FACILITY_DISPATCH = FACILITY_DISPATCH << 16;
        public const int PART_FACILITY_STORAGE = FACILITY_STORAGE << 16;
        public const int PART_FACILITY_ITF = FACILITY_ITF << 16;
        public const int PART_FACILITY_WIN32 = FACILITY_WIN32 << 16;
        public const int PART_FACILITY_WINDOWS = FACILITY_WINDOWS << 16;
        public const int PART_FACILITY_SECURITY = FACILITY_SECURITY << 16;
        public const int PART_FACILITY_SSPI = FACILITY_SSPI << 16;
        public const int PART_FACILITY_CONTROL = FACILITY_CONTROL << 16;
        public const int PART_FACILITY_CERT = FACILITY_CERT << 16;
        public const int PART_FACILITY_INTERNET = FACILITY_INTERNET << 16;
        public const int PART_FACILITY_MEDIASERVER = FACILITY_MEDIASERVER << 16;
        public const int PART_FACILITY_MSMQ = FACILITY_MSMQ << 16;
        public const int PART_FACILITY_SETUPAPI = FACILITY_SETUPAPI << 16;
        public const int PART_FACILITY_SCARD = FACILITY_SCARD << 16;
        public const int PART_FACILITY_COMPLUS = FACILITY_COMPLUS << 16;
        public const int PART_FACILITY_AAF = FACILITY_AAF << 16;
        public const int PART_FACILITY_URT = FACILITY_URT << 16;
        public const int PART_FACILITY_ACS = FACILITY_ACS << 16;
        public const int PART_FACILITY_DPLAY = FACILITY_DPLAY << 16;
        public const int PART_FACILITY_UMI = FACILITY_UMI << 16;
        public const int PART_FACILITY_SXS = FACILITY_SXS << 16;
        public const int PART_FACILITY_WINDOWS_CE = FACILITY_WINDOWS_CE << 16;
        public const int PART_FACILITY_HTTP = FACILITY_HTTP << 16;
        public const int PART_FACILITY_USERMODE_COMMONLOG = FACILITY_USERMODE_COMMONLOG << 16;

        public const int PART_FACILITY_USERMODE_FILTER_MANAGER = FACILITY_USERMODE_FILTER_MANAGER << 16;
        public const int PART_FACILITY_BACKGROUNDCOPY = FACILITY_BACKGROUNDCOPY << 16;
        public const int PART_FACILITY_CONFIGURATION = FACILITY_CONFIGURATION << 16;
        public const int PART_FACILITY_STATE_MANAGEMENT = FACILITY_STATE_MANAGEMENT << 16;
        public const int PART_FACILITY_METADIRECTORY = FACILITY_METADIRECTORY << 16;
        public const int PART_FACILITY_WINDOWSUPDATE = FACILITY_WINDOWSUPDATE << 16;
        public const int PART_FACILITY_DIRECTORYSERVICE = FACILITY_DIRECTORYSERVICE << 16;
        public const int PART_FACILITY_GRAPHICS = FACILITY_GRAPHICS << 16;
        public const int PART_FACILITY_SHELL = FACILITY_SHELL << 16;

        public const int PART_FACILITY_TPM_SERVICES = FACILITY_TPM_SERVICES << 16;
        public const int PART_FACILITY_TPM_SOFTWARE = FACILITY_TPM_SOFTWARE << 16;

        public const int PART_FACILITY_PLA = FACILITY_PLA << 16;
        public const int PART_FACILITY_FVE = FACILITY_FVE << 16;

        public const int PART_FACILITY_FWP = FACILITY_FWP << 16;
        public const int PART_FACILITY_WINRM = FACILITY_WINRM << 16;
        public const int PART_FACILITY_NDIS = FACILITY_NDIS << 16;
        public const int PART_FACILITY_USERMODE_HYPERVISOR = FACILITY_USERMODE_HYPERVISOR << 16;
        public const int PART_FACILITY_CMI = FACILITY_CMI << 16;
        public const int PART_FACILITY_USERMODE_VIRTUALIZATION = FACILITY_USERMODE_VIRTUALIZATION << 16;
        public const int PART_FACILITY_USERMODE_VOLMGR = FACILITY_USERMODE_VOLMGR << 16;
        public const int PART_FACILITY_BCD = FACILITY_BCD << 16;
        public const int PART_FACILITY_USERMODE_VHD = FACILITY_USERMODE_VHD << 16;

        public const int PART_FACILITY_SDIAG = FACILITY_SDIAG << 16;
        public const int PART_FACILITY_WEBSERVICES = FACILITY_WEBSERVICES << 16;

        public const int PART_FACILITY_WINDOWS_DEFENDER = FACILITY_WINDOWS_DEFENDER << 16;
        public const int PART_FACILITY_OPC = FACILITY_OPC << 16;

        #endregion

        public const int S_OK = 0;
        public const int S_FALSE = 1;

        public const int E_ABORT = FLAG_SEVERITY | 0x4004;
        public const int E_ACCESSDENIED = FLAG_SEVERITY | PART_FACILITY_WIN32 | 0x5;
        public const int E_FAIL = FLAG_SEVERITY | 0x4005;
        public const int E_HANDLE = FLAG_SEVERITY | PART_FACILITY_WIN32 | 0x6;
        public const int E_INVALIDARG = FLAG_SEVERITY | PART_FACILITY_WIN32 | 0x57;
        public const int E_NOINTERFACE = FLAG_SEVERITY | 0x4002;
        public const int E_NOTIMPL = FLAG_SEVERITY | 0x4001;
        public const int E_OUTOFMEMORY = FLAG_SEVERITY | PART_FACILITY_WIN32 | 0xE;
        public const int E_POINTER = FLAG_SEVERITY | 0x4003;
        public const int E_UNEXPECTED = FLAG_SEVERITY | 0xFFFF;

        public const int TYPE_E_ELEMENTNOTFOUND = FLAG_SEVERITY | PART_FACILITY_DISPATCH | 0x802B;
        public const int SCRIPT_E_REPORTED = FLAG_SEVERITY | PART_FACILITY_DISPATCH | 0x101;
        public const int SCRIPT_E_PROPAGATE = FLAG_SEVERITY | PART_FACILITY_DISPATCH | 0x102;
        public const int SCRIPT_E_RECORDED = FLAG_SEVERITY | 0x6664004;
    }
}

namespace OmniKits.Windows.Interop
{
    using EssIL;

    using static COM;

    [Flags]
    public enum HResult : int
    {
        FlagFailure = FLAG_SEVERITY,
        FlagR = FLAG_RESERVED,
        FlagCustomer = FLAG_CUSTOMER,
        FlagNTStatus = FLAG_NTSTATUS,
        FlagX = FLAG_X,

        CodeMask = 0x0000FFFF,

        FacilityMask = 0x07FF0000,

        #region Facilities

        FacilityNull = PART_FACILITY_NULL,
        FacilityRPC = PART_FACILITY_RPC,
        FacilityDispatch = PART_FACILITY_DISPATCH,
        FacilityStorage = PART_FACILITY_STORAGE,
        FacilityInterface = PART_FACILITY_ITF,
        FacilityWin32 = PART_FACILITY_WIN32,
        FacilityWindows = PART_FACILITY_WINDOWS,
        FacilitySecurity = PART_FACILITY_SECURITY,
        FacilitySSPI = PART_FACILITY_SSPI,
        FacilityControl = PART_FACILITY_CONTROL,
        FacilityCertificate = PART_FACILITY_CERT,
        FacilityInternet = PART_FACILITY_INTERNET,
        FacilityMediaServer = PART_FACILITY_MEDIASERVER,
        FacilityMSMQ = PART_FACILITY_MSMQ,
        FacilitySetupAPI = PART_FACILITY_SETUPAPI,
        FacilitySmartCard = PART_FACILITY_SCARD,
        FacilityComPlus = PART_FACILITY_COMPLUS,
        FacilityAnimatedAgent = PART_FACILITY_AAF,
        FacilityUniversalRuntime = PART_FACILITY_URT,
        FacilityAuditCollectionService = PART_FACILITY_ACS,
        FacilityDirectPlay = PART_FACILITY_DPLAY,
        FacilityUbiquitousMemoryIntrospection = PART_FACILITY_UMI,
        FacilitySxS = PART_FACILITY_SXS,
        FacilityWindowsCE = PART_FACILITY_WINDOWS_CE,
        FacilityHTTP = PART_FACILITY_HTTP,
        FacilityUserModeCommonLogging = PART_FACILITY_USERMODE_COMMONLOG,

        FacilityUserModeFilterManager = PART_FACILITY_USERMODE_FILTER_MANAGER,
        FacilityBackgroundCopy = PART_FACILITY_BACKGROUNDCOPY,
        FacilityConfiguration = PART_FACILITY_CONFIGURATION,
        FacilityStateManagement = PART_FACILITY_STATE_MANAGEMENT,
        FacilityMETADirectory = PART_FACILITY_METADIRECTORY,
        FacilityWindowsUpdate = PART_FACILITY_WINDOWSUPDATE,
        FacilityDirectoryService = PART_FACILITY_DIRECTORYSERVICE,
        FacilityGraphics = PART_FACILITY_GRAPHICS,
        FacilityShell = PART_FACILITY_SHELL,

        FacilityTpmServices = PART_FACILITY_TPM_SERVICES,
        FacilityTpmSoftware = PART_FACILITY_TPM_SOFTWARE,

        FacilityPerformanceLogsNAlerts = PART_FACILITY_PLA,
        FacilityFullVolumeEncryption = PART_FACILITY_FVE,

        FacilityFirewallPlatform = PART_FACILITY_FWP,
        FacilityWindowsResourceManager = PART_FACILITY_WINRM,
        FacilityNetworkDriverInterface = PART_FACILITY_NDIS,
        FacilityUserModeHypervisor = PART_FACILITY_USERMODE_HYPERVISOR,
        FacilityConfigurationManagementInfrastructure = PART_FACILITY_CMI,
        FacilityUserModeVirtualization = PART_FACILITY_USERMODE_VIRTUALIZATION,
        FacilityUserModeVolumeManager = PART_FACILITY_USERMODE_VOLMGR,
        FacilityBootConfigurationDatabase = PART_FACILITY_BCD,
        FacilityUserModeVHD = PART_FACILITY_USERMODE_VHD,

        FacilitySystemDiagnostics = PART_FACILITY_SDIAG,
        FacilityWebServices = PART_FACILITY_WEBSERVICES,

        FacilityWindowsDefender = PART_FACILITY_WINDOWS_DEFENDER,
        FacilityOpenConnectivityService = PART_FACILITY_OPC,

        #endregion

        SuccessOkay = S_OK,
        SuccessFalse = S_FALSE,

        ErrorAccessDenied = E_ACCESSDENIED,
        ErrorAbort = E_ABORT,
        ErrorFail = E_FAIL,
        ErrorHandle = E_HANDLE,
        ErrorInvalidArgument = E_INVALIDARG,
        ErrorNoInterface = E_NOINTERFACE,
        ErrorNotImplemented = E_NOTIMPL,
        ErrorOutOfMemory = E_OUTOFMEMORY,
        ErrorPointer = E_POINTER,
        ErrorUnexpected = E_UNEXPECTED,

        TypeErrorElementNotFound = TYPE_E_ELEMENTNOTFOUND,
        ScriptErrorReported = SCRIPT_E_REPORTED,
        ScriptErrorPropagated = SCRIPT_E_PROPAGATE,
        ScriptErrorRecorded = SCRIPT_E_RECORDED,
    }

    public static class HResultEx
    {
        public static bool IsSuccessed(this HResult hResult)
            => !hResult.IsFailed();
        public static bool IsFailed(this HResult hResult)
            => hResult.Has(HResult.FlagFailure);

        //HRESULT_CODE
        //HRESULT_FACILITY
        //HRESULT_FROM_NT
        //HRESULT_FROM_WIN32
        //HRESULT_SEVERITY
        //MAKE_HRESULT
        //MAKE_SCODE
        //OLESTR
        //SCODE_CODE
        //SCODE_FACILITY
        //SCODE_SEVERITY
    }
}
